using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web;
using System.Security.Permissions;

namespace Lanjian.Framework
{
	/// <summary>
	/// Provides the ability to toggle the visibility of another serverside control.
	/// </summary>
	[DefaultProperty("Text")]
	[ToolboxData("<{0}:ExpanderPanel runat=server></{0}:ExpanderPanel>")]
	[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
	public class ExpanderPanel : WebControl, INamingContainer
	{

		private static readonly string scriptKey = "Lanjian.Framework.ExpanderPanel";

		private HtmlInputHidden tracker;
		private Label headerLabel;
		private ImageButton button;

		/// <exclude />
		protected override HtmlTextWriterTag TagKey
		{
			get { return HtmlTextWriterTag.Div; }
		}

		#region CompositeControl Pattern

		/// <exclude />
		public override ControlCollection Controls
		{
			get
			{
				EnsureChildControls();
				return base.Controls;
			}
		}


		#endregion

		#region Properties

		#region Button

		/// <summary>
		/// Gets or sets the url of the image shown in the toggle button when the target control is in view.
		/// </summary>
		[
		System.ComponentModel.Editor("System.Web.UI.Design.ImageUrlEditor, System.Design", typeof(System.Drawing.Design.UITypeEditor)),
		System.ComponentModel.Description("Collapse link image URL"),
		System.ComponentModel.DefaultValue(""),
		UrlProperty()
		]
		public virtual string ButtonImage
		{
			get
			{
				object state = ViewState["ButtonImage"];
				if (state != null)
					return (string)state;
				return "";
			}
			set{ViewState["ButtonImage"] = value;}
		}

		/// <summary>
		/// Gets or sets the url of the image shown in the toggle button when the target control is hidden.
		/// </summary>
		[
		System.ComponentModel.Editor("System.Web.UI.Design.ImageUrlEditor, System.Design", typeof(System.Drawing.Design.UITypeEditor)),
		System.ComponentModel.Description("Collapse link image URL"),
		System.ComponentModel.DefaultValue(""),
		UrlProperty()
		]
		public virtual string ButtonImageCollapsed
		{
			get
			{
				object state = ViewState["ButtonImageCollapsed"];
				if (state != null)
					return (string)state;
				return "";
			}
			set { ViewState["ButtonImageCollapsed"] = value; }
		}

		/// <summary>
		/// Gets or sets the css class of the toggle button
		/// </summary>
		[
		System.ComponentModel.DefaultValue(""),
		]
		public virtual string ButtonCssClass
		{
			get
			{
				object state = ViewState["ButtonCssClass"];
				if (state != null)
					return (string)state;
				return "";
			}
			set { ViewState["ButtonCssClass"] = value; }
		}

		#endregion

		#region Text

		/// <summary>
		/// Gets or sets the text shown next to the toggle button
		/// </summary>
		[
		System.ComponentModel.DefaultValue("Caption"),
		]
		public virtual string Text
		{
			get
			{
				object state = ViewState["Text"];
				if (state != null)
					return (string)state;
				return "Caption";
			}
			set { ViewState["Text"] = value; }
		}

		/// <summary>
		/// Gets or sets the css class of the text next to the toggle button
		/// </summary>
		[
		System.ComponentModel.DefaultValue(""),
		]
		public virtual string TextCssClass
		{
			get
			{
				object state = ViewState["TextCssClass"];
				if (state != null)
					return (string)state;
				return "";
			}
			set { ViewState["TextCssClass"] = value; }
		}

		#endregion

		/// <summary>
		/// Gets or sets the ID of the control which is the target of the visibility-toggling behavior.
		/// </summary>
		[
		Description("Gets or sets the ID of the control which is the target of the visibility-toggling behavior."),
		Category("Behavior"),
		DefaultValue(""),
		]
		public virtual string ControlToToggle
		{
			get
			{
				object savedState = ViewState["ControlToToggle"];
				if (savedState != null)
					return (string)savedState;
				return "";
			}
			set
			{
				ViewState["ControlToToggle"] = value;
				cachedTargetControl = null;
			}
		}


		/// <summary>
		/// Gets or sets whether the target control is visible or not
		/// </summary>
		[
		System.ComponentModel.DefaultValue(false),
		]
		public virtual bool Collapsed
		{
			get
			{
				object state = ViewState["Collapsed"];
				if (state != null)
					return (bool)state;
				return false;
			}
			set
			{
				ViewState["Collapsed"] = value;
			}
		}


		/// <summary>
		/// Gets or sets the order of the button and text
		/// </summary>
		[
		System.ComponentModel.DefaultValue(System.Web.UI.WebControls.TextAlign.Left),
		]
		public virtual System.Web.UI.WebControls.TextAlign TextAlign
		{
			get
			{
				object state = ViewState["TextAlign"];
				if (state != null)
					return (TextAlign)state;
				return TextAlign.Left;
			}
			set { ViewState["TextAlign"] = value; }
		}

		#endregion

		#region Lifecycle

		/// <exclude />
		protected override void CreateChildControls()
		{

			Controls.Clear();

			tracker = new HtmlInputHidden();
			tracker.Name = "tracker";
			tracker.ID = "tracker";
			tracker.ServerChange += new EventHandler( ClientExpanedStateChanged );
			Controls.Add(tracker);

			headerLabel = new Label();
			headerLabel.ID = "label";
			Controls.Add( headerLabel );

			button = new ImageButton();
			button.CausesValidation = false;
			button.ID = "clicker";
			button.Click += new System.Web.UI.ImageClickEventHandler( button_Click );
			Controls.Add(button);

		}

		/// <exclude />
		protected override void OnPreRender(EventArgs e)
		{
			EnsureChildControls();

			base.OnPreRender(e);

			//if (!csContext.User.EnableCollapsingPanels)
			//    Collapsed = false;

			if (!Page.ClientScript.IsClientScriptBlockRegistered(scriptKey))
				Page.ClientScript.RegisterClientScriptBlock(this.GetType(), scriptKey, string.Format("<script type='text/javascript' language='javascript' src='{0}'></script>", Page.ResolveUrl("~/Utility/ExpanderPanelScript.js")));

			tracker.Value = Collapsed.ToString();

			if (Collapsed)
				TargetStyle["display"] = "none";
			else
			{
				if (TargetStyle["display"] != null)
					TargetStyle.Remove("display");
			}
		}

		/// <exclude />
		protected override void Render( HtmlTextWriter writer )
		{
			if ( Page != null ) 
				Page.VerifyRenderingInServerForm( this );

			ApplyPropertiesToChildren();

			base.Render( writer );
		}

		private void ApplyPropertiesToChildren() 
		{
			EnsureChildControls();

			if ( TextAlign == TextAlign.Right )
			{
				Controls.Remove( headerLabel );
				Controls.Add( headerLabel );
			}

			button.Attributes[ "onclick" ] =
				string.Format(
					"return ExpanderPanel_Toggle('{0}','{1}','{2}','{3}','{4}');", 
					TargetControl.ClientID,
					button.ClientID, 
					tracker.ClientID,
					ResolveUrl( ButtonImage ), 
					ResolveUrl( ButtonImageCollapsed )
				);

			button.CssClass = ButtonCssClass;

			headerLabel.Text = Text;
			headerLabel.CssClass = TextCssClass;

			if ( Collapsed )
				button.ImageUrl = ResolveUrl( ButtonImage );
			 else 
				button.ImageUrl = ResolveUrl( ButtonImageCollapsed );
		}

		#endregion

		#region Event Handlers

		private void ClientExpanedStateChanged(object sender, EventArgs e)
		{
			try
			{
				bool clientExpanedValue = bool.Parse(tracker.Value);
				Collapsed = clientExpanedValue;
			}
			catch { }
		}

		private void button_Click(object sender, ImageClickEventArgs e)
		{
			Collapsed = !Collapsed;
		}

		#endregion

		#region Target Control

		private Control TargetControl
		{
			get
			{
				if (cachedTargetControl == null)
				{
					cachedTargetControl = NamingContainer.FindControl(ControlToToggle);
				}
				return cachedTargetControl;
			}
		}
		private Control cachedTargetControl = null;

		private CssStyleCollection TargetStyle
		{
			get
			{
				WebControl targetWebControl = TargetControl as WebControl;
				if (targetWebControl != null)
					return targetWebControl.Style;
				
				HtmlControl targetHtmlControl = TargetControl as HtmlControl;
				if (targetHtmlControl != null)
					return targetHtmlControl.Style;
				return null;
			}
		}

		#endregion
	}
}
